package com.hitqz.robot.driver.listener;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.google.common.util.concurrent.RateLimiter;
import com.hitqz.robot.api.business.event.TrackRemoteModeTriggerEvent;
import com.hitqz.robot.api.business.event.TrackStopTriggerEvent;
import com.hitqz.robot.api.business.event.TrackUltrasonicTriggerEvent;
import com.hitqz.robot.api.common.dto.robot.RobotGoTargetPosDto;
import com.hitqz.robot.api.common.dto.robot.RobotOnlineEventDto;
import com.hitqz.robot.api.common.entity.Robot;
import com.hitqz.robot.api.common.entity.RobotMapPos;
import com.hitqz.robot.driver.HitTrackRobotDriverImpl;
import com.hitqz.robot.driver.communication.NetworkServiceThreadPool;
import com.hitqz.robot.driver.dto.CalculateLocateDto;
import com.hitqz.robot.driver.dto.LocateStatusDto;
import com.hitqz.robot.driver.dto.PowerInfoDto;
import com.hitqz.robot.driver.util.TrackCacheUtil;
import com.hitqz.robot.driver.util.TrackToolkit;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

@Component
@AllArgsConstructor
@Slf4j
public class TrackSelfListener {

    // 创建一个具有单一线程的调度执行器
    private final static ScheduledExecutorService delayChargeScheduler = Executors.newScheduledThreadPool(1);
    // 运行中计数限流器
    private final static RateLimiter runningCountLimiter = RateLimiter.create(1);
    private final static AtomicInteger runningCount = new AtomicInteger(0);
    private static int lastMileage;
    //定位事件处理
    @EventListener
    public void onLocationEvent(LocateStatusDto event){
        NetworkServiceThreadPool.dealEvent(()->{
            byte locatedStatus = event.getLocatedStatus();
            short lastId = event.getLastId();
            short nextId = event.getNextId();
            int mileage = event.getMileage();
            boolean isReach = false;
            String stationCode = String.valueOf(lastId);
            if (locatedStatus==(byte)2 && lastId == nextId) {
                //到达点位
                runningCount.set(0);
                isReach = true;
                //已经到了目标点，清空信息，避免误触发恢复前往的时间
                if (TrackToolkit.currentTargetCode.contains("-") &&
                        ArrayUtil.contains(TrackToolkit.currentTargetCode.split("-"), String.valueOf(lastId))) {
                    TrackToolkit.currentTargetCode = "";
                } else if (TrackToolkit.currentTargetCode.equals(String.valueOf(lastId))) {
                    TrackToolkit.currentTargetCode = "";
                }
                for (String s : CollUtil.emptyIfNull(TrackToolkit.posMap.keySet())) {
                    if (s.contains("-") && ArrayUtil.contains(s.split("-"), stationCode)){
                        stationCode = s;
                        break;
                    }
                }
                // 处理充电标志
                if (TrackToolkit.chargeFlag){
                    TrackToolkit.chargeFlag = false; // 重置充电标志
                    delayChargeScheduler.schedule(()->{
                        LocateStatusDto currentStatus = (LocateStatusDto) TrackCacheUtil.get(TrackCacheUtil.KEY_LOCATE_STATUS);
                        // 仍在坞站,可以充电
                        if (currentStatus.getLastId()==currentStatus.getNextId() && currentStatus.getLastId() ==(short)0) {
                            TrackToolkit.setChargeStatus((byte) 1);
                        }else {
                            log.info("[track]delay charge but not in charge station now");
                        }
                    },3, TimeUnit.SECONDS);
                }
            }
            if (locatedStatus!=(byte)2 && lastMileage == mileage) {
                //行驶中且长时间保持不动,重新下发点位
                if (runningCountLimiter.tryAcquire()){
                    int count = runningCount.getAndIncrement();
                    if (count > 60){
                        //60秒内不动
                        runningCount.set(0);
                        if (StrUtil.isNotBlank(TrackToolkit.currentTargetCode)) {
                            log.info("[track]long time no go,re sent go target,{}",TrackToolkit.currentTargetCode);
                            HitTrackRobotDriverImpl service = SpringUtil.getBean(HitTrackRobotDriverImpl.class);
                            service.robotTaskGoTarget(RobotGoTargetPosDto.builder().code(TrackToolkit.currentTargetCode).build());
                        }
                    }
                }
            }
            lastMileage = mileage;
            //计算像素坐标
            int pixelX = 0;
            int pixelY = 0;
            if (lastId==-1 && nextId == -1){
                //刚开机位置不确定
            } else if (lastId == -1){
                //扫到错误标签
            }else {
                RobotMapPos lastPos = TrackToolkit.posMap.get(stationCode);
                //todo 站点中间的进行计算
                pixelX = lastPos.getPixelX();
                pixelY = lastPos.getPixelY();
            }
            CalculateLocateDto calculateLocateDto = CalculateLocateDto.builder()
                    .currentStation(stationCode)
                    .isReach(isReach)
                    .pixelX(pixelX)
                    .pixelY(pixelY)
                    .build();
            TrackCacheUtil.put(TrackCacheUtil.KEY_CALCULATE_LOCATION, calculateLocateDto);
        });
    }




    @EventListener
    public void onUltrasonicEvent(TrackUltrasonicTriggerEvent event){
        NetworkServiceThreadPool.dealEvent(()->{
            try {
                if (event.getFrontUltrasonicTriggerStatus() == 1 || event.getBackUltrasonicTriggerStatus() == 1) {
                    //超声波触发
                    return;
                }
                // 超声波释放
                if (StrUtil.isBlank(TrackToolkit.currentTargetCode)) {
                    log.info("ultrasonic release,no target");
                    return;
                }
                Thread.sleep(1000);
                HitTrackRobotDriverImpl service = SpringUtil.getBean(HitTrackRobotDriverImpl.class);
                service.robotTaskGoTarget(RobotGoTargetPosDto.builder().code(TrackToolkit.currentTargetCode).build());
                log.info("[track]ultrasonic release, go to target,{}", TrackToolkit.currentTargetCode);
            }catch (Exception e){
                log.error("[track]ultrasonic release error",e);
            }
        });
    }

    @EventListener
    public void onRemoteTriggerEvent(TrackRemoteModeTriggerEvent event){
        NetworkServiceThreadPool.dealEvent(()->{
            try {
                if (event.getRemoteTriggerStatus() == 1) {
                    return;
                }
                // 远程模式释放
                if (StrUtil.isBlank(TrackToolkit.currentTargetCode)) {
                    log.info("remote release,no target");
                    return;
                }
                Thread.sleep(1000);
                HitTrackRobotDriverImpl service = SpringUtil.getBean(HitTrackRobotDriverImpl.class);
                service.robotTaskGoTarget(RobotGoTargetPosDto.builder().code(TrackToolkit.currentTargetCode).build());
                log.info("[track]remote release, go to target,{}", TrackToolkit.currentTargetCode);
            }catch (Exception e){
                log.info("[track]remote release error",e);
            }
        });
    }


    @EventListener
    public void onStopTriggerEvent(TrackStopTriggerEvent event){
        NetworkServiceThreadPool.dealEvent(()->{
            try {
                if (event.getStopTriggerStatus() == 1) {
                    return;
                }
                // 急停释放
                if (StrUtil.isBlank(TrackToolkit.currentTargetCode)) {
                    log.info("stop release,no target");
                    return;
                }
                Thread.sleep(1000);
                HitTrackRobotDriverImpl service = SpringUtil.getBean(HitTrackRobotDriverImpl.class);
                service.robotTaskGoTarget(RobotGoTargetPosDto.builder().code(TrackToolkit.currentTargetCode).build());
                log.info("[track]stop release, go to target,{}", TrackToolkit.currentTargetCode);
            }catch (Exception e){
                log.info("[track]stop release error",e);
            }
        });
    }

    @EventListener
    public void onOnlineEvent(RobotOnlineEventDto event){
        //上线逻辑
        if (Objects.equals(event.getOnlineStatus(),1)){
            if (StrUtil.isNotBlank(TrackToolkit.currentTargetCode)){
                HitTrackRobotDriverImpl service = SpringUtil.getBean(HitTrackRobotDriverImpl.class);
                service.robotTaskGoTarget(RobotGoTargetPosDto.builder().code(TrackToolkit.currentTargetCode).build());
                log.info("[track]online, go to target,{}", TrackToolkit.currentTargetCode);
            }
        }


    }



}
